package com.lihui.TCP;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

/**
 * 功能描述
 *
 * @author wileda
 * @date 2023/02/19  14:53
 */
public class TCPEchoServer  {
    //声明用于服务端的类
    protected ServerSocket socket;


    public TCPEchoServer(int port) throws IOException {
        if(port < 1025 || port > 65535){
            throw new BindException("端口号建议在1025-65535之间");
        }
        this.socket = new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务已经启动，等待客户端的连接.");
        //循环接收客户端的连接
        while(true){
            //接收客户端的请求
            Socket clintSocket = socket.accept();
            //交给专门的方法处理
            processConnections(clintSocket);
        }
    }

    private void processConnections(Socket clintSocket) throws IOException {
        System.out.printf("[%s:%d] 客户端已上线.\n", clintSocket.getInetAddress().toString(), clintSocket.getPort());
        // 所有的通信数据都在Socket的对象中clintSocket，TCP传输的数据是字节流的形式
        //1.获取输入流
        try(InputStream inputStream = clintSocket.getInputStream();
            OutputStream outputStream = clintSocket.getOutputStream()){
            //2.循环处理客户发来的信息
            while(true){
                //Scanner来简化字符串的读取
                Scanner scanner = new Scanner(inputStream);
                //3.判断是否还有下一行
                if(!scanner.hasNextLine()){
                    //没有数据了，客户端下线
                    System.out.printf("[%s:%d]客户端已经下线。\n",clintSocket.getInetAddress().toString(),clintSocket.getPort());
                    break;
                }
                //4.获取用户发来的信息具体内容
                String request = scanner.nextLine();
                //5.根据请求内容计算响应
                String response = process(request);
                //6.1把响应返回给客户端
                PrintWriter writer = new PrintWriter(outputStream);
                //6.2向输出流中写入数据
                writer.println(response);
                writer.flush();
                // 7. 打印日志
                System.out.printf("[%s:%d] request = %s, response = %s\n", clintSocket.getInetAddress().toString(),
                        clintSocket.getPort(), request, response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            clintSocket.close();
        }
    }

    protected String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TCPEchoServer server = new TCPEchoServer(9090);
        server.start();
    }
}
